package es.uned.etsii.si3.taller;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

import java.sql.SQLException;
import java.util.List;

@DatabaseTable(tableName = "usuarios")
public
class Usuario extends Persistente {
	public static final String ID_FIELD_NAME = "id";
	public static final String USUARIO_FIELD_NAME = "usuario";
	public static final String ROL_CLIENTE = "cliente";
	public static final String ACTIVO_FIELD_NAME = "activo";
	public static final String ESCLIENTE_FIELD_NAME = "esCliente";
	public static final String EMAIL_FIELD_NAME = "email";

	@DatabaseField(generatedId = true, columnName = ID_FIELD_NAME)
	int id;
	@DatabaseField(width = 20, index = true, columnName = USUARIO_FIELD_NAME)
	String usuario;
	@DatabaseField(width = 32)
	String password;
	@DatabaseField(width = 100, index = true, columnName = EMAIL_FIELD_NAME)
	String email;
	@DatabaseField(columnName = ESCLIENTE_FIELD_NAME)
	boolean esCliente;
	@DatabaseField(columnName = ACTIVO_FIELD_NAME)
	boolean activo;

	/**
	 * Factoría para crear nuevos usuarios partiendo de un conjunto de datos,
	 * al tiempo que se crear el objeto en la base de datos
	 *
	 * @param  username  identificador del usuario en la web
	 * @param  clave     clave en claro
	 * @param  email     dirección de correo electrónico
	 * @param  esCliente marca verdadero si este usuario es un cliente, falso si es empleado
	 * @return          un nuevo objeto, ya guardado en la base de datos
	 */
	public
	static Usuario crear(String username, String clave, String email,
			boolean esCliente) throws SQLException
	{
		Usuario usuario = new Usuario();

		usuario.setUsuario(username);
		usuario.setPassword(clave);
		usuario.setEmail(email);
		usuario.setEsCliente(esCliente);
		usuario.setActivo(false);
		getClassDao(Usuario.class).create(usuario);

		return usuario;
	}
	
	public
	static void crear(Usuario usuario) throws SQLException {
		getClassDao(Usuario.class).create(usuario);
	}

	/**
	 * Busca un usuario por su nombre
	 * @param username
	 * @return el usuario
	 * @throws SQLException
	 */
	public
	static Usuario buscarPorNombreUsuario(String username) throws SQLException {
		List<Usuario> usuarios = getClassDao(Usuario.class).queryForEq(USUARIO_FIELD_NAME, username);

		if (usuarios.size() == 0)
			return null;

		if (usuarios.size() > 1) {
			return null;
		}

		return usuarios.get(0);
	}

	public
	Usuario() {
		// ORM Lite necesita un constructor por defecto
	}

	public int     getId()        { return id; }
	public String  getUsuario()   { return usuario; }
	public String  getPassword()  { return password; }
	public String  getEmail()     { return email; }
	public boolean getEsCliente() { return esCliente; }
	public boolean getActivo()    { return activo; }

	public
	Cliente getCliente() throws SQLException {
		if (!esCliente)
			return null;

		return Cliente.buscarPorUsuario(this);
	}

	public
	Empleado getEmpleado() throws SQLException {
		if (esCliente)
			return null;

		return Empleado.buscarPorUsuario(this);
	}

	public
	void setUsuario(String usuario) {
		this.usuario = usuario;
	}

	public
	void setPassword(String password) {
		this.password = password;
	}

	public
	void setEmail(String email) {
		this.email = email;
	}

	public
	void setEsCliente(boolean esCliente) {
		this.esCliente = esCliente;
	}

	public
	void setActivo(boolean activo) {
		this.activo = activo;
	}

	/**
	 * Permite activar un usuario
	 * @throws SQLException
	 */
	public
    void activar() throws SQLException {
		setActivo(true);
		update();
	}

	/**
	 * Permite desactivar un usuario
	 * @throws SQLException
	 */
	public
	void desactivar() throws SQLException {
		setActivo(false);
		update();
	}
	
	public
	boolean claveCorrecta(String clave) {
		return getPassword().equals(clave);
	}
	
	/**
	 * Función accesoria para actualizar datos de un usuario partiendo
	 * de los campos de otro objeto Usuario. Los datos actualizados son el
	 * nombre de usuario, su dirección de correo y la clave.
	 * 
	 * Si {@code datosUsuario} es @null, no se produce ningún cambio, pero no
	 * se informa de ello de ninguna manera.
	 * 
	 * Si algún campo es @null, no se actualiza, permitiendo así actualizaciones
	 * parciales.
	 * 
	 * @param datosUsuario   instancia de Usuario con los datos nuevos
	 * @throws SQLException  lanzada en caso de problemas al tratar con la base de datos
	 */
	public
	void actualizar(Usuario datosUsuario) throws SQLException {
		if (datosUsuario == null) {
			return;
		}
		
		if (datosUsuario.getUsuario() != null)
			setUsuario(datosUsuario.getUsuario());
		
		if (datosUsuario.getEmail() != null)
			setEmail(datosUsuario.getEmail());
		
		if (datosUsuario.getPassword() != null)
			setPassword(datosUsuario.getPassword());
		
		update();
	}
}